package com.cfw.util;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;

/**
 * 문자열에 대한 Utility Class
 * <br/><b>History</b><br/>
 * <pre>
 * 2012. 4. 19. 최초작성
 * </pre>
 * @author 박형일
 * @version 1.0
 */
public final class PatternUtil {
	final private static String MSG_PAR_TAG_NULL =	"매개변수 tag문자열이  null입니다.";
	final private static String MSG_PAR_SRC_NULL =	"매개변수 원본문자열이  null입니다.";
	final private static String MSG_PAR_PTN_NULL =	"매개변수 패턴문자열이  null입니다.";
	final private static String MSG_PAR_FNM_EMPTY =	"매개변수 파일명이 null이거나 빈문자열입니다.";

	private PatternUtil() {} 
	
	/**
	 * ... <tag>{target}</tag> ... 형식의 문자열에서 {target}문자열들을 추출하여 반환
	 * @param tag
	 * @param src
	 * @return
	 * @throws IllegalArgumentException
	 * @throws PatternSyntaxException
	 */
	public static List<String> getTagInnerStrings(final String tag, final String src) throws IllegalArgumentException, PatternSyntaxException {
		if (tag == null) {
			throw new IllegalArgumentException(PatternUtil.MSG_PAR_TAG_NULL);
		} else
		if (src == null) {
			throw new IllegalArgumentException(PatternUtil.MSG_PAR_SRC_NULL);
		}
		
		final StringBuffer buf = new StringBuffer(100);

		buf.append("(?<=<")
			.append(tag)
			.append(">)(?:(?!<")
			.append(tag)
			.append(">).)*?(?=</")
			.append(tag)
			.append(">)");
		return getPatternStrings(buf.toString(), src);
	}
	
	/**
	 * ... <tag>{target}</tag> ... 형식의 문자열에서 첫번째 매치된 {target}문자열을 추출하여 반환
	 * @param tag
	 * @param src
	 * @return
	 * @throws IllegalArgumentException
	 * @throws PatternSyntaxException
	 */
	public static String getTagInnerString(final String tag, final String src) throws IllegalArgumentException, PatternSyntaxException {
		if (tag == null) {
			throw new IllegalArgumentException(PatternUtil.MSG_PAR_TAG_NULL);
		} else
		if (src == null) {
			throw new IllegalArgumentException(PatternUtil.MSG_PAR_SRC_NULL);
		}		
		
		final StringBuffer buf = new StringBuffer(100);
		
		buf.append("(?<=<")
			.append(tag)
			.append(">)(?:(?!<")
			.append(tag)
			.append(">).)*?(?=</")
			.append(tag)
			.append(">)");
		return getPatternString(buf.toString(), src);
	}	
	
		private static Matcher getMatcher(final String rxp, final String src) {
			if (rxp == null) {
				throw new IllegalArgumentException(PatternUtil.MSG_PAR_PTN_NULL);
			} else
			if (src == null) {
				throw new IllegalArgumentException(PatternUtil.MSG_PAR_SRC_NULL);
			}		
			
	        final Pattern pattern = Pattern.compile(rxp, Pattern.DOTALL);
	        
	        return pattern.matcher(src);
		}
		
	/**
	 * rxp 정규식을 이용하여 src에서 문자열들을 추출하여 반환
	 * @param rxp
	 * @param src
	 * @return
	 * @throws IllegalArgumentException
	 * @throws PatternSyntaxException
	 */
	public static List<String> getPatternStrings(final String rxp, final String src) throws IllegalArgumentException, PatternSyntaxException {
		final Matcher matcher = getMatcher(rxp, src);
		
		final ArrayList<String> result = new ArrayList<String>();
		while (matcher.find()) {
			for (int i = 0; i <= matcher.groupCount(); i++) {
				result.add(matcher.group(i));
			}
		}
		
		return result;
	}
	
	/**
	 * rxp 정규식을 이용하여 src에서 추출된 첫번째 문자열 반환
	 * @param rxp
	 * @param src
	 * @return
	 * @throws IllegalArgumentException
	 * @throws PatternSyntaxException
	 */
	public static String getPatternString(final String rxp, final String src) throws IllegalArgumentException, PatternSyntaxException {
		final Matcher matcher = getMatcher(rxp, src);
		
		String result = "";
		if (matcher.find()) {
			result = matcher.group(0);
		}
		return result;
	}

	/**
	 * rxp 정규식을 이용하여 src에서 추출된 seq번째 문자열 반환
	 * @param rxp
	 * @param src
	 * @param seq
	 * @return
	 * @throws IllegalArgumentException
	 * @throws PatternSyntaxException
	 */
	public static String getPatternString(final String rxp, final String src, final int seq) throws IllegalArgumentException, PatternSyntaxException {
		final Matcher matcher = getMatcher(rxp, src);
		
		String result = "";
		if (matcher.find() && (matcher.groupCount() >= seq)) { 
			result = matcher.group(seq);
		} else {
			result = "";
		}
		return result;
	}		
	
	/**
	 * target정규식에 패턴 매칭되는 source 문자열이 array에 포함되어 있는지 여부를 반환.
	 * NOTE: target이 null일 경우 false 반환	 
	 * @param source
	 * @param target
	 * @return
	 */
	public static boolean match(final String[] source, final String target) {
		boolean result =	false;
		
		for (int i = 0; target != null && source != null && i < source.length; i++) {
			if (source[i].matches(target)) { 
				result = true;
				break;
			}
		}
		
		return result;
	}
	
	/**
	 * Deprecated org.apache.commons.lang3.StringEscapeUtils.escapeEcmaScript(String input)를 대신 사용
	 * javascript 문자열로 변환, \n, \r, \ 문자열을 처리함
	 * @param src
	 * @return
	 */
	@Deprecated
	public static String cvtJSString(final String src) {
		String cvt = "";
		cvt = StringUtils.defaultString(src).replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replaceAll("\"", "\\\\\"");
		
		return cvt;
	}
	
	/**
	 * Deprecated org.apache.commons.lang3.StringEscapeUtils.escapeHtml4(String input) 를 대신 사용
	 * 문자열을 HTML문자열로 변환
	 * @param s
	 * @return
	 */
	@Deprecated
	public static String cvtHTMLString(final String str) {
		final String buf = StringUtils.defaultString(str).
			replaceAll("&", "&amp;").
			replaceAll("<", "&lt;").
			replaceAll(">", "&gt;").
			replaceAll("\n", "<br/>").
			replaceAll("\r", "").
			replaceAll("\'", "&#39;").
			replaceAll("\"", "&quot;");
		return buf;
	}
	 
	/**
	 * Deprecated org.apache.commons.lang3.ArrayUtils.contains(Object[] array, Object objectToFind) 를 대신 사용
	 * target문자열이 source 문자열 array에 포함되어 있는지 여부를 반환.
	 * NOTE: target이 null일 경우 false 반환
	 * @param source
	 * @param target
	 * @return
	 */
	@Deprecated
	public static boolean isInStringArray(final String[] source, final String target) {
		boolean result =	false;
		
		for (int i = 0; target != null && source != null && i < source.length; i++) {
			if (target.equals(source[i])) {
				result =	true;
				break;
			}
		}
		
		return result;
	}
	
}
